#ifndef __BSTREEWORDID_H__
#define __BSTREEWORDID_H__

#include <iostream>
#include <string>
#include "../indice/invertedindex/src/includes/file_pointer_pack.h"
#include "../indice/invertedindex/src/includes/register_pack.h"



class KeyKeyValId : public Register{
	private:
		unsigned int idKey;
	public:
		KeyKeyValId(unsigned int idKey){
			this->idKey=idKey;
		}

		KeyKeyValId(const KeyKeyValId& k2){
			this->idKey=k2.getKey();
		}

		~KeyKeyValId(){
		}
		
		unsigned int getKey()const{
			return this->idKey;
		}

		Register* duplicate()const{
			return (new KeyKeyValId(*this));
		}

		void setFields(const Register& b2){
			const KeyKeyValId& temp = dynamic_cast<const KeyKeyValId&>(b2);
			this->idKey = temp.getKey();
		}

		unsigned int getSize()const {
			return sizeof(unsigned int);
		};

		bool operator<(const Register& b2)const{
			const KeyKeyValId& temp = dynamic_cast<const KeyKeyValId&>(b2);

			unsigned int w1=this->getKey();
			unsigned int w2=temp.getKey();

			return w1<w2;
		}

		std::ostream& toOstream(std::ostream& out)const{
			out << this->idKey;
			return out;
		}
};


class KeyValId : public Register{

	private:
		unsigned int keyLength;
		char* key;
		unsigned int idKey;
	public:
		KeyValId(unsigned int keyLength, const char* key, unsigned int idKey){
			this->key=new char[keyLength];
			memcpy(this->key,key,keyLength);
			this->keyLength=keyLength;
			this->idKey = idKey;
		}
		KeyValId(const KeyValId& k2){
			std::pair<unsigned int, char*> keyAux=k2.getKey();
			this->key = keyAux.second;
			this->keyLength = keyAux.first;
			this->idKey = k2.getIdKey();
		}

		~KeyValId(){
			delete[] key;
		}

		std::pair<unsigned int, char*> getKey()const{ 
			std::pair<unsigned int, char*> ret(this->keyLength,NULL);
			ret.second = new char[this->keyLength];
			memcpy(ret.second, this->key, this->keyLength);
			return ret;  
		}
		unsigned int getIdKey()const{ return this->idKey; }

		
		void setKey(unsigned int keyLength, char* key){
			this->keyLength = keyLength;
			delete[] this->key;
			this->key = new char[keyLength];
			memcpy(this->key, key, keyLength);
			
		}
		void setIdKey(unsigned int idKey){ this->idKey=idKey; }
		
		Register* duplicate()const{
			return (new KeyValId(*this));
		}

		void setFields(const Register& b2){
			const KeyValId& temp = dynamic_cast<const KeyValId&>(b2);
			std::pair<unsigned int, char*> keyAux=temp.getKey();
			delete[] this->key;
			this->keyLength=keyAux.first;
			this->key=keyAux.second;
			this->idKey = temp.getIdKey();
		}

		unsigned int getSize()const {
			unsigned int ret=0;
			ret=sizeof(unsigned int)*2+keyLength;
			return ret;
		};

		bool operator<(const Register& b2)const{
			const KeyValId& temp = dynamic_cast<const KeyValId&>(b2);
			
			unsigned int w1=this->getIdKey();
			unsigned int w2=temp.getIdKey();

			return w1<w2;
		}

		Register* getKeyRegister()const{
			KeyKeyValId* reg = new KeyKeyValId(this->idKey);
			return reg;
		}

		std::ostream& toOstream(std::ostream& out)const{
			char* temp=key;
			unsigned int i;
			out << "\t\t";
			for(i=0; i<keyLength; i++){
				out<<*temp;
				temp++;
			}
			out << std::endl;
			out << "\t\t KeyLength   : " << this->keyLength << std::endl;
			out << "\t\t IdKey : " << this->idKey << std::endl;
			return out;
		}
};


class KeyKeyValFactoryId : public RegisterFactory{
	public:
		KeyKeyValFactoryId(){}
		~KeyKeyValFactoryId(){}

		RegisterFactory* duplicate()const{ return new KeyKeyValFactoryId(); }

		Register* operator ()(char* data)const{
			unsigned int val;
			memcpy(&val,data,sizeof(unsigned int));
			return (new KeyKeyValId(val));
		}
		
		char* operator ()(const Register& reg,char* data)const{
			const KeyKeyValId& kkvreg = dynamic_cast<const KeyKeyValId&>(reg);
			char* temp = data;
			unsigned int tempKey = kkvreg.getKey();
			memcpy(temp,&tempKey,sizeof(unsigned int));
			temp += sizeof(unsigned int);
			return temp;
		}
};

class KeyValFactoryId : public RegisterFactory{
	private:
		static const unsigned int NOFILEPOINTER=-1;
	public:
		KeyValFactoryId(){}
		~KeyValFactoryId(){}

		RegisterFactory* duplicate()const{ return new KeyValFactoryId(); }

		Register* operator ()(char* data)const{
			char* temp = data;
			unsigned int IdKey;
			unsigned int keyLength;
			char* keyTemp;

			memcpy(&keyLength,temp,sizeof(unsigned int));
			temp += sizeof(unsigned int);
			
			keyTemp = new char[keyLength];
			memcpy(keyTemp,temp,keyLength);
			temp += keyLength;

			memcpy(&IdKey,temp,sizeof(unsigned int));
			temp += sizeof(unsigned int);

			KeyValId* kv = new KeyValId(keyLength,keyTemp,IdKey);

			delete[] keyTemp;

			return (kv);
		}
		
		char* operator ()(const Register& reg,char* data)const{
			const KeyValId& kvreg = dynamic_cast<const KeyValId&>(reg);
			char* temp = data;
			unsigned int tempIdKey = kvreg.getIdKey();
			std::pair<unsigned int, char*> tempKey = kvreg.getKey();
			unsigned int keyLength = tempKey.first;

			memcpy(temp,&keyLength,sizeof(unsigned int));
			temp+=sizeof(unsigned int);
			
			memcpy(temp,tempKey.second,tempKey.first);
			temp+=tempKey.first;
			delete[] tempKey.second;

			memcpy(temp,&tempIdKey,sizeof(unsigned int));
			temp+=sizeof(unsigned int);
			
			return temp;
		}
};



#endif // __BSTREEWORDID_H__
